---
title: "Announcing v0.17: Triggers and Improved ERDs"
authors: rotemtam
tags: [release, erd, schemadoc, triggers, postgres, mysql, mariadb, sqlite]
---

import InstallationInstructions from '../../md/components/_installation_instructions.mdx'

Hi everyone,

I hope you are enjoying the holiday season, because we are here today with the first Atlas
release of 2024: [v0.17](https://github.com/ariga/atlas/releases/tag/v0.17.0).  It's been
only a bit over a week since our last release, but we have some exciting new features we
couldn't wait to share with you:

* **Trigger Support** - Atlas now supports managing triggers on MySQL, PostgreSQL, MariaDB and SQLite databases.
* **Improved ERDs** - You can now visualize your schema's SQL views, as well as create filters to select the specific
database objects you wish to see.

Without further ado, let's dive in!

### Trigger Support

:::info BETA FEATURE
Triggers are currently in beta and available to logged-in users only. To use this feature, run:

```
atlas login
```

:::

Triggers are a powerful feature of relational databases that allow you to run custom
code when certain events occur on a table or a view. For example, you can use triggers to
automatically update the amount of stock in your inventory when a new order is
placed or to create an audit log of changes to a table. Using this event-based approach,
you can implement complex business logic in your database, without having to write
any additional code in your application.

Managing triggers as part of the software development lifecycle can be quite a challenge.
Luckily, Atlas's database schema-as-code approach makes it easy to do!

Let's use Atlas to build a small chunk of a simple e-commerce application:

1. Download the latest version of the Atlas CLI:
   <InstallationInstructions/>
2. Make sure you are logged in to Atlas:
   ```
   atlas login
   ```
3. Let's spin up a new PostgreSQL database using `docker`:

    ```bash
    docker run --name db -e POSTGRES_PASSWORD=pass -d -p 5432:5432 postgres:16
    ```
4. Next, let's define and apply the base tables for our application:

   ```hcl title=schema.hcl
    table "inventory" {
      schema = schema.public
      column "item_id" {
        null = false
        type = serial
      }
      column "item_name" {
        null = false
        type = character_varying(255)
      }
      column "quantity" {
        null = false
        type = integer
      }
      primary_key {
        columns = [column.item_id]
      }
    }
    table "orders" {
      schema = schema.public
      column "order_id" {
        null = false
        type = serial
      }
      column "item_id" {
        null = false
        type = integer
      }
      column "order_quantity" {
        null = false
        type = integer
      }
      primary_key {
        columns = [column.order_id]
      }
      foreign_key "orders_item_id_fkey" {
        columns     = [column.item_id]
        ref_columns = [table.inventory.column.item_id]
        on_update   = NO_ACTION
        on_delete   = NO_ACTION
      }
    }
    ```
    This defines two tables: `inventory` and `orders`. The `inventory` table holds
    information about the items in our store, and the `orders` table holds information
    about orders placed by our customers. The `orders` table has a foreign key
    constraint to the `inventory` table, to ensure that we can't place an order for
    an item that doesn't exist in our inventory.

    Apply this schema on our local Postgres instance using the Atlas CLI:

    ```bash
    atlas schema apply \
       --dev-url 'docker://postgres/16?search_path=public' \
       --to file://schema.hcl \
       -u 'postgres://postgres:pass@:5432/postgres?search_path=public&sslmode=disable' \
       --auto-approve
    ```
    This command will apply the schema defined in `schema.hcl` to the local Postgres instance.
    Notice the `--auto-approve` flag, which instructs Atlas to automatically apply the schema
    without prompting for confirmation.

5.  Let's now populate our database with some inventory items. We can do this using
    the `psql` command that is installed inside the default PostgreSQL Docker image:

    ```bash
    docker exec -it db psql -U postgres -c "INSERT INTO inventory (item_name, quantity) VALUES ('Apple', 10);"
    docker exec -it db psql -U postgres -c "INSERT INTO inventory (item_name, quantity) VALUES ('Banana', 20);"
    docker exec -it db psql -U postgres -c "INSERT INTO inventory (item_name, quantity) VALUES ('Orange', 30);"
    ```

6. Now, let's define the business logic for our store using a `FUNCTION` and a `TRIGGER`. Append
   these definitions to `schema.hcl`:
   ```hcl title=schema.hcl (continued)
    function "update_inventory" {
      schema = schema.public
      lang   = PLpgSQL
      return = trigger
      as     = <<-SQL
      BEGIN
          UPDATE inventory
          SET quantity = quantity - NEW.order_quantity
          WHERE item_id = NEW.item_id;
          RETURN NEW;
      END;
      SQL
    }
    trigger "after_order_insert" {
      on = table.orders
      after {
        insert = true
      }
      foreach = ROW
      execute {
        function = function.update_inventory
      }
    }
    ```
    We start by defining a `FUNCTION` called `update_inventory`. This function is
    written in `PL/pgSQL`, the procedural language for PostgreSQL. The function
    accepts a single argument, which is a `TRIGGER` object. The function updates
    the `inventory` table to reflect the new order, and then returns the `NEW`
    row, which is the row that was just inserted into the `orders` table.

    Next, we define a `TRIGGER` called `after_order_insert`. This trigger is
    executed after a new row is inserted into the `orders` table. The trigger
    executes the `update_inventory` function for each row that was inserted.

    Apply the updated schema using the Atlas CLI:
    ```bash
    atlas schema apply \
       --dev-url 'docker://postgres/16?search_path=public' \
       --to file://schema.hcl \
       -u 'postgres://postgres:pass@:5432/postgres?search_path=public&sslmode=disable' \
       --auto-approve
    ```
    Notice that Atlas automatically detects that we have added a new `FUNCTION`
    and a new `TRIGGER`, and applies them to the database.
7. Finally, let's test our application to see that it actually works. We can do
   this by inserting a new row into the `orders` table:
   ```bash
   docker exec -it db psql -U postgres -c "INSERT INTO orders (item_id, order_quantity) VALUES (1, 5);"
   ```
   This statement creates a new order for 5 `Apple`s.

   Now, let's check the `inventory` table to see that the order was processed
   correctly:

   ```bash
   docker exec -it db psql -U postgres -c "SELECT quantity FROM inventory WHERE item_name='Apple';"
   ```
   You should see the following output:
   ```
    quantity
    ---------
            5
   (1 row)
   ```

   Amazing! Our trigger automatically detected the creation of a new order of apples,
   and updated the inventory accordingly from 10 to 5.


### Improved ERDs

One of the most frequently used capabilities in Atlas is schema visualization. Having a visual representation of your
data model can be helpful as it allows for easier comprehension of complex data structures, and enables
developers to better understand and collaborate on the data model of the application they are building.

#### Visualizing Database Views

![erd-views](https://atlasgo.io/uploads/blog/v0.17/erd-views.png)

Until recently, the ERD showed schema's tables and the relations between them. With the most recent release,
the ERD now visualizes database views!

Within each view you can find its:

 * Columns - the view's columns, including their data types and nullability.
 * Create Statement - the SQL CREATE statement, based on your specific database type.
 * Dependencies - a list of the tables (or other views) it is connected to. Clicking on this
 will map edges to each connected object in the schema.

As of recently (including this release), we have added support for functions, stored procedures and triggers which are all
coming soon to the ERD!

To play with a schema that contains this feature, head over to the [live demo](https://gh.atlasgo.cloud/dirs/4294967296).

#### ERD Filters

In cases where you have many database objects and prefer to focus in on a specific set of tables and views,
you can narrow down your selection by creating a filter. Filters can be saved for future use. This can be great when working
on a feature that affects a specific part of the schema, this way you can easily refer to it as needed.

![erd-filters](https://atlasgo.io/uploads/images/erd-filters2.png)

### Wrapping up

That's it! I hope you try out (and enjoy) all of these new features and find them useful.
As always, we would love to hear your feedback and suggestions on our [Discord server](https://discord.gg/zZ6sWVg6NT).
